<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
  <meta name="baidu-site-verification" content="code-UjJKh3jtOo">
  <link rel="stylesheet" href="//unpkg.com/@highlightjs/cdn-assets@11.5.0/styles/atom-one-dark.min.css">
  <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
  <title>Tit1e</title>
  <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-2767111597631391" crossorigin="anonymous"></script>
  
<link rel="stylesheet" href="/css/style.css">

<meta name="generator" content="Hexo 6.3.0"><link rel="alternate" href="/atom.xml" title="Tit1e" type="application/atom+xml">
</head>

<body class="dark">
    <div class="container">
    <header class="header">
  <div class="title">
      <a href="/" class="logo">Tit1e</a>
      <div class="btn-dark"></div>
      <script>
        let bodyClx = document.body.classList;
        let btnDark = document.querySelector('.btn-dark');
        let sysDark = window.matchMedia('(prefers-color-scheme: dark)');
        let darkVal = localStorage.getItem('dark');

        let setDark = (isDark) => {
        bodyClx[isDark ? 'add' : 'remove']('dark');
        localStorage.setItem('dark', isDark ? 'yes' : 'no');
        };

        setDark(darkVal ? darkVal === 'yes' : sysDark.matches);
        requestAnimationFrame(() => bodyClx.remove('not-ready'));

        btnDark.addEventListener('click', () => setDark(!bodyClx.contains('dark')));
        sysDark.addEventListener('change', (event) => setDark(event.matches));
      </script>
  </div>
    <ul class="menu">
        
        
        
        
        <li class="menu-item ">
            <a href="/" class="menu-item-link">Home</a>
        </li>
        
        
        <li class="menu-item ">
            <a href="/archives/" class="menu-item-link">Archives</a>
        </li>
        
        
        <li class="menu-item ">
            <a href="/atom.xml" class="menu-item-link">RSS</a>
        </li>
        
        
        <li class="menu-item ">
            <a target="_blank" rel="noopener" href="https://pixeltimer.art" class="menu-item-link">Pixel Timer</a>
        </li>
        
    </ul>
    <div class="search-box">
        <input type="search" id="search" placeholder="搜索">
    </div>
</header>
    <article class="post">
  <div class="post-meta">
    <span class="post-time">4 / 14, 2020</span>
  </div>
  <div class="post-title">
    <h1 class="title">element-ui el-table 表格高度自适应问题解决方案</h1>
  </div>
  
  <ul class="post-tags">
    
    <li class="tag-item">
      #学习
    </li>
    
  </ul>
  
  <div class="post-content">
    <p>工作中由于公司业务需要，要求 table 做到整个 table 始终能在页面上完全显示， head 固定，body 超出滚动，由于公司使用的是 element-ui，el-table 组件提供了 height 属性，但是这个属性的值必须是具体的像素，因此，当页面的窗口大小发生变化时，想要表格高度自适应，一般的做法就是监听窗口大小是否改变，如果改变了就重新计算 table 的高度，然后重新设置。我之前的做法是这样的：</p>
<p>我们公司基本都是后台应用，结构差不多就是这个样子，菜单与顶栏的宽度与高度是固定的，而且菜单部分与表格高度的计算其实没有关系。</p>
<p><img src="https://personal-1251959693.cos.ap-chengdu.myqcloud.com/2020-04-14-134209.png"></p>
<p>因此我计算表格高度的时候，一般都是：</p>
<p>整个网页的高度 - 顶栏的高度 - 各种 margin，padding 的高度 &#x3D; 表格高度</p>
<p>然后监听窗口的变化：</p>
<pre><code class="javascript">window.addEventListener(&#39;resize&#39;, () =&gt; &#123;
    //重新计算高度
&#125;)
</code></pre>
<p>直到后来我遇到了这个需求：</p>
<p>页面分为左右两部分，可拖动改变左侧部分的宽度，右侧还是自适应。乍一看这个左侧改变宽度跟右侧好像没什么关系，原来那套也适用啊，但是再仔细一想，左侧改变了有可能导致右侧筛选条件宽度不够而换行，一换行筛选条件的高度就改变了，这时候是需要重新计算高度的，但是上面监听的代码只监听窗口大小改变，而现在的情况窗口的大小并没有被改变，只是 div 的宽度发生了变化，后来我 google 了一圈，发现了 <a target="_blank" rel="noopener" href="https://github.com/marcj/css-element-queries">css-element-queries</a> 这个库中的 <code>ResizeSensor</code>  这个类可以实现对元素大小改变的监听，使用方法也很简单：</p>
<pre><code class="javascript">/**
 * element 需要监听的元素
 */
new ResizeSensor(element, () =&gt; &#123;
    //callback
  //重新计算高度
&#125;)
</code></pre>
<p>并且在这次调整的过程中，我想到了用 flex 属性来让右侧的筛选条件跟 table 自行分配空间，因为这类表格的页面结构基本是固定的，上面是筛选条件，下面是表格，于是我封装了一个  <code>&lt;form-page&gt;</code> 组件，结构就是大概 是这样：</p>
<p><img src="https://personal-1251959693.cos.ap-chengdu.myqcloud.com/2020-04-14-141421.png"></p>
<p>这个结构下，我就不用再去关心除了筛选条件的高度外我还需要减去多少的额外高度，我只要关心我的 table slot 区域有多少高度，我就把 table 设为多少高度就可以了。</p>
<p>当然内容展示区域的高度是需要计算过的，但是这个只要在全局样式中用 <code>calc</code> 计算一次高度就可以了。</p>
<p>下面是 demo 的演示效果：</p>
<p><video src="https://personal-1251959693.cos.ap-chengdu.myqcloud.com/2020-04-14-element-ui-table-auto-height.mp4" style="width: 100%" controls ></video></p>
<p><a target="_blank" rel="noopener" href="https://github.com/Tit1e/element-ui-table-auto-height">demo 源码</a></p>
<p><strong>2020年8月27日更新：</strong></p>
<p>目前 2.13 版本的 table 已经支持height&#x3D;“100%”，所以可以放弃上面的实现方式了。</p>

  </div>
  <div class="post-near">
    
    <a
      class="post-near-prev"
      href="/p/7721161.html"
      title="uni-app 小程序设置自定义字体"
    >
      <span class="arrow">←</span>
      <span class="post-near-title">
        uni-app 小程序设置自定义字体
      </span>
    </a>
    
    
    <a
      class="post-near-next"
      href="/p/9d1c1cab.html"
      title="AppleScript 初尝试"
    >
      <span class="post-near-title">
        AppleScript 初尝试
      </span>
      <span class="arrow">→</span>
    </a>
    
  </div>
</article>

    <footer class="footer">
  <p>本博客采用 <a class="license-link" rel="license noopener" target="_blank" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh">署名-非商业性使用-相同方式共享 4.0 国际</a>协议进行许可</p>
  <p>
    <span>Thanks For <a target="_blank" rel="noopener" href="https://github.com/nanxiaobei/hugo-paper" taget="_blank">hugo-paper</a></span>
    <span style="margin-left: 10px;">&copy; 2016-2025 by Tit1e</span>
  </p>
</footer>
    </div>
    <script src="//unpkg.com/@highlightjs/cdn-assets@11.5.0/highlight.min.js"></script>
<script>
  hljs.initHighlightingOnLoad();
  var _hmt = _hmt || [];
    (function() {
    var hm = document.createElement("script");
    hm.src = "https://hm.baidu.com/hm.js?6349d3bc54baea0b04a65145c5e3b799";
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(hm, s);
    })();
    const block = document.querySelectorAll('.post-content')[0]
    block.addEventListener('click', e => {
        const {nodeName, src} = e.target
        if(nodeName !== 'IMG') return
        document.body.classList.add('overflow-hidden')
        const div = document.createElement('div')
        div.id = 'global-cover'
        div.title = '点击关闭'
        const a = document.createElement('a')
        a.href = src
        a.target="_blank"
        a.title = '点击打开原图'
        const img = document.createElement('img')
        img.className = 'show-pic'
        img.src = src
        a.appendChild(img)
        div.appendChild(a)
        document.body.appendChild(div)
    })
    document.body.addEventListener('click', e => {
        if(e.target.id === 'global-cover'){
            document.body.classList.remove('overflow-hidden')
            document.body.removeChild(e.target)
        }
    })
</script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-7M04VN3JZ4"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-7M04VN3JZ4');
</script>

<script src="/js/search.js"></script>


</body>
</html>